require 'RNotify'
require 'gtk2'

#sudo apt-get install build-essential ruby1.8-dev libnotify-dev ruby-gnome2

module Autotest::RNotify
  class Notification
    
    ICON_PENDING = "#{Dir.pwd}/public/images/autotest/pending.png"
    ICON_PASS = "#{Dir.pwd}/public/images/autotest/pass.png"
    ICON_FAIL = "#{Dir.pwd}/public/images/autotest/fail.png"
    EXPIRATION_IN_SECONDS = 5
    URGENCY_LOW = Notify::Notification::URGENCY_LOW
    URGENCY_NORMAL = Notify::Notification::URGENCY_NORMAL
    URGENCY_CRITICAL = Notify::Notification::URGENCY_CRITICAL
    
    attr_accessor :verbose, :image_root, :tray_icon, :notification
    
    def initialize(verbose = false)
      self.verbose = verbose
      
      puts 'Autotest Hook: loading Notify' if verbose
      Notify.init('Autotest') || raise('Failed to initialize Notify')

      puts 'Autotest Hook: initializing tray icon' if verbose
      self.tray_icon = Gtk::StatusIcon.new
      tray_icon.icon_name = 'face-monkey'
      tray_icon.tooltip = 'RSpec Autotest'

      puts 'Autotest Hook: Creating Notifier' if verbose
      self.notification = Notify::Notification.new('X', nil, nil, tray_icon)
      notification.timeout = timeout
      
      Thread.new { Gtk.main }
      sleep 1
      tray_icon.embedded? || raise('Failed to set up tray icon')
    end
    
    def timeout
      EXPIRATION_IN_SECONDS * 1000
    end
    
    def notify(icon, tray, title, message, urgency = URGENCY_NORMAL)
      notification.update(title, message, nil)
      notification.pixbuf_icon = icon
      notification.urgency = urgency
      
      tray_icon.tooltip = "Last Result: #{message}"
      tray_icon.icon_name = tray
      notification.show
    end
    
    def passed(title, message)
      notify(image_pass, 'face-smile', title, message, URGENCY_NORMAL)
    end
    
    def pending(title, message)
      notify(image_pending, 'face-plain', title, message, URGENCY_NORMAL)
    end
    
    def failed(title, message) 
      notify(image_fail, 'face-sad', title, message, URGENCY_CRITICAL)
    end
    
    def quit
      puts 'Autotest Hook: Shutting Down...' if verbose
      #Notify.uninit
      Gtk.main_quit
    end
    
    def image_pass
      Gdk::Pixbuf.new(ICON_PASS, 48,48)
    end
    
    def image_fail
      Gdk::Pixbuf.new(ICON_FAIL, 48,48)
    end
    
    def image_pending
      Gdk::Pixbuf.new(ICON_PENDING, 48,48)
    end
    
  end

end

Autotest.add_hook :initialize do |at|
  @notify = Autotest::RNotify::Notification.new
end

Autotest.add_hook :ran_command do |at|
  output = at.results.last
  
  tests = 0
  assertions = 0
  failures = 0
  errors = 0
  
  unless output.nil?
    output.scan(/(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/) do |t, a, f, e|
      tests += t.to_i
      assertions += a.to_i
      failures += f.to_i
      errors += e.to_i
    end

    if errors > 0 || tests < 1
      @notify.failed("Error(s) while running tests", output)
    elsif failures > 0
      @notify.failed("Tests Failed", output)
    else
      unless at.tainted
        @notify.passed("All Tests Passed", output)
      else
        @notify.passed("Tests Passed", output)
      end
    end
  end
end

Autotest.add_hook :quit do |at|
  @notify.quit
end